import { Quat } from "./Quat";
import { Vec3 } from "./Vec3";
import { ArrayType, EPSILON } from "./common";
/**
 * 4*4矩阵
 * @class
 * @author jsbrml
 */
class Mat4 extends ArrayType {
    /**
     * 构造函数。
     * @constructor
     * @example
     * let mat=new Mat4();
     */
    constructor(element = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]) {
        super(element);
    }
    /**
     * 4阶矩阵的克隆。
     * @method
     * @public
     * @example
     * let mat4=new Mat4();
     * let clone=mat4.clone();
     * @returns {Mat4} Mat4。
     */
    clone() {
        return new Mat4(this);
    }
    /**
     * 4阶矩阵的拷贝。
     * @method
     * @public
     * @example
     * let mat4=new Mat4();
     * let copy=new Mat4();
     * copy.copy(mat4);
     * @returns {Mat4} Mat4。
     */
    copy(m) {
        this[0] = m[0];
        this[1] = m[1];
        this[2] = m[2];
        this[3] = m[3];
        this[4] = m[4];
        this[5] = m[5];
        this[6] = m[6];
        this[7] = m[7];
        this[8] = m[8];
        this[9] = m[9];
        this[10] = m[10];
        this[11] = m[11];
        this[12] = m[12];
        this[13] = m[13];
        this[14] = m[14];
        this[15] = m[15];
        return this;
    }
    /**
     * 将矩阵设置为单位矩阵。
     * @method
     * @public
     * @example
     * let mat=new Mat4([3,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * mat.identity();
     * @returns {Mat4} 单位矩阵
     */
    identity() {
        this[0] = 1;
        this[1] = 0;
        this[2] = 0;
        this[3] = 0;
        this[4] = 0;
        this[5] = 1;
        this[6] = 0;
        this[7] = 0;
        this[8] = 0;
        this[9] = 0;
        this[10] = 1;
        this[11] = 0;
        this[12] = 0;
        this[13] = 0;
        this[14] = 0;
        this[15] = 1;
        return this;
    }
    /**
     * 4阶矩阵的等式判断。
     * @method
     * @public
     * @example
     * let mat4=new Mat4();
     * let mat42=new Mat4();
     * let isEqual=mat4.equal(mat42);//true
     * @returns {Boolean} 是否相等。
     */
    equal(v) {
        let a0 = this[0],
            a1 = this[1],
            a2 = this[2],
            a3 = this[3];
        let a4 = this[4],
            a5 = this[5],
            a6 = this[6],
            a7 = this[7];
        let a8 = this[8],
            a9 = this[9],
            a10 = this[10],
            a11 = this[11];
        let a12 = this[12],
            a13 = this[13],
            a14 = this[14],
            a15 = this[15];

        let b0 = v[0],
            b1 = v[1],
            b2 = v[2],
            b3 = v[3];
        let b4 = v[4],
            b5 = v[5],
            b6 = v[6],
            b7 = v[7];
        let b8 = v[8],
            b9 = v[9],
            b10 = v[10],
            b11 = v[11];
        let b12 = v[12],
            b13 = v[13],
            b14 = v[14],
            b15 = v[15];
        return (
            Math.abs(a0 - b0) <=
            EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
            Math.abs(a1 - b1) <=
            EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
            Math.abs(a2 - b2) <=
            EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&
            Math.abs(a3 - b3) <=
            EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) &&
            Math.abs(a4 - b4) <=
            EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) &&
            Math.abs(a5 - b5) <=
            EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) &&
            Math.abs(a6 - b6) <=
            EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) &&
            Math.abs(a7 - b7) <=
            EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) &&
            Math.abs(a8 - b8) <=
            EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) &&
            Math.abs(a9 - b9) <=
            EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) &&
            Math.abs(a10 - b10) <=
            EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) &&
            Math.abs(a11 - b11) <=
            EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) &&
            Math.abs(a12 - b12) <=
            EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) &&
            Math.abs(a13 - b13) <=
            EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) &&
            Math.abs(a14 - b14) <=
            EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) &&
            Math.abs(a15 - b15) <=
            EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15))
        );
    }
    /**
     * 对4阶矩阵进行转置变换。
     * @method
     * @public
     * @example
     * let mat=new Mat4([3,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * mat.transpose();
     * @returns {Mat4} 转置矩阵
     */
    transpose() {
        let a = this.clone();//克隆
        this[0] = a[0];
        this[1] = a[4];
        this[2] = a[8];
        this[3] = a[12];
        this[4] = a[1];
        this[5] = a[5];
        this[6] = a[9];
        this[7] = a[13];
        this[8] = a[2];
        this[9] = a[6];
        this[10] = a[10];
        this[11] = a[14];
        this[12] = a[3];
        this[13] = a[7];
        this[14] = a[11];
        this[15] = a[15];
        a = null;
        return this;
    }
    /**
     * 对4阶矩阵进行逆变换。
     * @method
     * @public
     * @example
     * let mat=new Mat4([3,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * mat.invert();
     * @returns {Mat4} 逆矩阵
     */
    invert() {
        let a00 = this[0],
            a01 = this[1],
            a02 = this[2],
            a03 = this[3];
        let a10 = this[4],
            a11 = this[5],
            a12 = this[6],
            a13 = this[7];
        let a20 = this[8],
            a21 = this[9],
            a22 = this[10],
            a23 = this[11];
        let a30 = this[12],
            a31 = this[13],
            a32 = this[14],
            a33 = this[15];

        let b00 = a00 * a11 - a01 * a10;
        let b01 = a00 * a12 - a02 * a10;
        let b02 = a00 * a13 - a03 * a10;
        let b03 = a01 * a12 - a02 * a11;
        let b04 = a01 * a13 - a03 * a11;
        let b05 = a02 * a13 - a03 * a12;
        let b06 = a20 * a31 - a21 * a30;
        let b07 = a20 * a32 - a22 * a30;
        let b08 = a20 * a33 - a23 * a30;
        let b09 = a21 * a32 - a22 * a31;
        let b10 = a21 * a33 - a23 * a31;
        let b11 = a22 * a33 - a23 * a32;

        // Calculate the determinant
        let det =
            b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;

        if (!det) {
            return null;
        }
        det = 1.0 / det;

        this[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
        this[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
        this[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
        this[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
        this[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
        this[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
        this[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
        this[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
        this[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
        this[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
        this[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
        this[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
        this[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
        this[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
        this[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
        this[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
        return this;
    }
    /**
     * 计算4阶矩阵的伴随阵。
     * @method
     * @public
     * @example
     * let mat=new Mat4([3,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * mat.adjoint();
     * @returns {Mat4} 伴随阵
     */
    adjoint() {
        let a00 = this[0],
            a01 = this[1],
            a02 = this[2],
            a03 = this[3];
        let a10 = this[4],
            a11 = this[5],
            a12 = this[6],
            a13 = this[7];
        let a20 = this[8],
            a21 = this[9],
            a22 = this[10],
            a23 = this[11];
        let a30 = this[12],
            a31 = this[13],
            a32 = this[14],
            a33 = this[15];

        let b00 = a00 * a11 - a01 * a10;
        let b01 = a00 * a12 - a02 * a10;
        let b02 = a00 * a13 - a03 * a10;
        let b03 = a01 * a12 - a02 * a11;
        let b04 = a01 * a13 - a03 * a11;
        let b05 = a02 * a13 - a03 * a12;
        let b06 = a20 * a31 - a21 * a30;
        let b07 = a20 * a32 - a22 * a30;
        let b08 = a20 * a33 - a23 * a30;
        let b09 = a21 * a32 - a22 * a31;
        let b10 = a21 * a33 - a23 * a31;
        let b11 = a22 * a33 - a23 * a32;

        this[0] = a11 * b11 - a12 * b10 + a13 * b09;
        this[1] = a02 * b10 - a01 * b11 - a03 * b09;
        this[2] = a31 * b05 - a32 * b04 + a33 * b03;
        this[3] = a22 * b04 - a21 * b05 - a23 * b03;
        this[4] = a12 * b08 - a10 * b11 - a13 * b07;
        this[5] = a00 * b11 - a02 * b08 + a03 * b07;
        this[6] = a32 * b02 - a30 * b05 - a33 * b01;
        this[7] = a20 * b05 - a22 * b02 + a23 * b01;
        this[8] = a10 * b10 - a11 * b08 + a13 * b06;
        this[9] = a01 * b08 - a00 * b10 - a03 * b06;
        this[10] = a30 * b04 - a31 * b02 + a33 * b00;
        this[11] = a21 * b02 - a20 * b04 - a23 * b00;
        this[12] = a11 * b07 - a10 * b09 - a12 * b06;
        this[13] = a00 * b09 - a01 * b07 + a02 * b06;
        this[14] = a31 * b01 - a30 * b03 - a32 * b00;
        this[15] = a20 * b03 - a21 * b01 + a22 * b00;
        return this;
    }
    /**
     * 计算4阶矩阵的行列式。
     * @method
     * @public
     * @example
     * let mat=new Mat4([3,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * mat.determinant();
     * @returns {Number} 返回矩阵det
     */
    determinant() {
        let a00 = this[0],
            a01 = this[1],
            a02 = this[2],
            a03 = this[3];
        let a10 = this[4],
            a11 = this[5],
            a12 = this[6],
            a13 = this[7];
        let a20 = this[8],
            a21 = this[9],
            a22 = this[10],
            a23 = this[11];
        let a30 = this[12],
            a31 = this[13],
            a32 = this[14],
            a33 = this[15];

        let b0 = a00 * a11 - a01 * a10;
        let b1 = a00 * a12 - a02 * a10;
        let b2 = a01 * a12 - a02 * a11;
        let b3 = a20 * a31 - a21 * a30;
        let b4 = a20 * a32 - a22 * a30;
        let b5 = a21 * a32 - a22 * a31;
        let b6 = a00 * b5 - a01 * b4 + a02 * b3;
        let b7 = a10 * b5 - a11 * b4 + a12 * b3;
        let b8 = a20 * b2 - a21 * b1 + a22 * b0;
        let b9 = a30 * b2 - a31 * b1 + a32 * b0;
        // Calculate the determinant
        return a13 * b6 - a03 * b7 + a33 * b8 - a23 * b9;
    }
    /**
     * 矩阵乘法
     * @method
     * @public
     * @param {Mat4} v 另外一个Mat4矩阵。
     * @example
     * let a=new Mat4([3,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * let b=new Mat4([2,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * a.multiply(b);//a变为乘后矩阵。
     * //如果保留a,则可以先克隆后乘。
     * let c=a.clone();
     * c.multiply(b);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    multiply(b) {
        let a00 = this[0],
            a01 = this[1],
            a02 = this[2],
            a03 = this[3];
        let a10 = this[4],
            a11 = this[5],
            a12 = this[6],
            a13 = this[7];
        let a20 = this[8],
            a21 = this[9],
            a22 = this[10],
            a23 = this[11];
        let a30 = this[12],
            a31 = this[13],
            a32 = this[14],
            a33 = this[15];

        // Cache only the current line of the second matrix
        let b0 = b[0],
            b1 = b[1],
            b2 = b[2],
            b3 = b[3];
        this[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        this[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        this[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        this[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;

        b0 = b[4];
        b1 = b[5];
        b2 = b[6];
        b3 = b[7];
        this[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        this[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        this[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        this[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;

        b0 = b[8];
        b1 = b[9];
        b2 = b[10];
        b3 = b[11];
        this[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        this[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        this[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        this[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;

        b0 = b[12];
        b1 = b[13];
        b2 = b[14];
        b3 = b[15];
        this[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        this[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        this[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        this[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
        return this;
    }
    /**
     * 矩阵左乘
     * @method
     * @public
     * @param {Mat4} v 另外一个Mat4矩阵。
     * @example
     * let a=new Mat4([3,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * let b=new Mat4([2,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * a.premultiply(b);//a变为乘后矩阵。
     * //如果保留a,则可以先克隆后乘。
     * let c=a.clone();
     * c.premultiply(b);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    premultiply(b) {
        const a00 = b[0],
            a01 = b[1],
            a02 = b[2],
            a03 = b[3];
        const a10 = b[4],
            a11 = b[5],
            a12 = b[6],
            a13 = b[7];
        const a20 = b[8],
            a21 = b[9],
            a22 = b[10],
            a23 = b[11];
        const a30 = b[12],
            a31 = b[13],
            a32 = b[14],
            a33 = b[15];

        // Cache only the current line of the second matrix
        let b0 = this[0],
            b1 = this[1],
            b2 = this[2],
            b3 = this[3];
        this[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        this[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        this[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        this[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;

        b0 = this[4];
        b1 = this[5];
        b2 = this[6];
        b3 = this[7];
        this[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        this[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        this[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        this[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;

        b0 = this[8];
        b1 = this[9];
        b2 = this[10];
        b3 = this[11];
        this[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        this[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        this[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        this[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;

        b0 = this[12];
        b1 = this[13];
        b2 = this[14];
        b3 = this[15];
        this[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        this[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        this[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        this[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
        return this;
    }
    /**
     * 矩阵平移变换
     * @method
     * @public
     * @param {Vec3} v 平移量。
     * @example
     * let a=new Mat4([3,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * a.translate([2,3,1]);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    translate(v) {
        const x = v[0],
            y = v[1],
            z = v[2];
        this[12] = this[0] * x + this[4] * y + this[8] * z + this[12];
        this[13] = this[1] * x + this[5] * y + this[9] * z + this[13];
        this[14] = this[2] * x + this[6] * y + this[10] * z + this[14];
        this[15] = this[3] * x + this[7] * y + this[11] * z + this[15];
        return this;
    }
    /**
     * 矩阵缩放变换
     * @method
     * @public
     * @param {Vec3} v 缩放量。
     * @example
     * let a=new Mat4([3,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * a.scale([2,3,1]);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    scale(v) {
        const x = v[0];
        const y = v[1];
        const z = v[2];
        this[0] *= x;
        this[1] *= x;
        this[2] *= x;
        this[3] *= x;
        this[4] *= y;
        this[5] *= y;
        this[6] *= y;
        this[7] *= y;
        this[8] *= z;
        this[9] *= z;
        this[10] *= z;
        this[11] *= z;
        return this;
    }
    /**
     * 矩阵旋转变换
     * @method
     * @public
     * @param {Number} rad 弧度。
     * @param {Vec3} v 缩放量。
     * @example
     * let a=new Mat4([3,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * a.rotate(Math.PI/3,[0,1,0]);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    rotate(rad, axis) {
        let x = axis[0];
        let y = axis[1];
        let z = axis[2];
        let len = Math.sqrt(x * x + y * y + z * z);
        if (len < EPSILON) {
            return null;
        }
        len = 1 / len;
        x *= len;
        y *= len;
        z *= len;
        const s = Math.sin(rad);
        const c = Math.cos(rad);
        const t = 1 - c;
        const a00 = this[0];
        const a01 = this[1];
        const a02 = this[2];
        const a03 = this[3];
        const a10 = this[4];
        const a11 = this[5];
        const a12 = this[6];
        const a13 = this[7];
        const a20 = this[8];
        const a21 = this[9];
        const a22 = this[10];
        const a23 = this[11];
        // Construct the elements of the rotation matrix
        const b00 = x * x * t + c;
        const b01 = y * x * t + z * s;
        const b02 = z * x * t - y * s;
        const b10 = x * y * t - z * s;
        const b11 = y * y * t + c;
        const b12 = z * y * t + x * s;
        const b20 = x * z * t + y * s;
        const b21 = y * z * t - x * s;
        const b22 = z * z * t + c;
        // Perform rotation-specific matrix multiplication
        this[0] = a00 * b00 + a10 * b01 + a20 * b02;
        this[1] = a01 * b00 + a11 * b01 + a21 * b02;
        this[2] = a02 * b00 + a12 * b01 + a22 * b02;
        this[3] = a03 * b00 + a13 * b01 + a23 * b02;
        this[4] = a00 * b10 + a10 * b11 + a20 * b12;
        this[5] = a01 * b10 + a11 * b11 + a21 * b12;
        this[6] = a02 * b10 + a12 * b11 + a22 * b12;
        this[7] = a03 * b10 + a13 * b11 + a23 * b12;
        this[8] = a00 * b20 + a10 * b21 + a20 * b22;
        this[9] = a01 * b20 + a11 * b21 + a21 * b22;
        this[10] = a02 * b20 + a12 * b21 + a22 * b22;
        this[11] = a03 * b20 + a13 * b21 + a23 * b22;
        return this;
    }
    /**
     * 矩阵绕x轴旋转变换
     * @method
     * @public
     * @param {Number} rad 弧度。
     * @example
     * let a=new Mat4([3,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * a.rotateX(Math.PI/3);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    rotateX(rad) {
        let s = Math.sin(rad);
        let c = Math.cos(rad);
        let a10 = this[4];
        let a11 = this[5];
        let a12 = this[6];
        let a13 = this[7];
        let a20 = this[8];
        let a21 = this[9];
        let a22 = this[10];
        let a23 = this[11];

        // Perform axis-specific matrix multiplication
        this[4] = a10 * c + a20 * s;
        this[5] = a11 * c + a21 * s;
        this[6] = a12 * c + a22 * s;
        this[7] = a13 * c + a23 * s;
        this[8] = a20 * c - a10 * s;
        this[9] = a21 * c - a11 * s;
        this[10] = a22 * c - a12 * s;
        this[11] = a23 * c - a13 * s;
        return this;
    }
    /**
     * 矩阵绕y轴旋转变换
     * @method
     * @public
     * @param {Number} rad 弧度。
     * @example
     * let a=new Mat4([3,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * a.rotateY(Math.PI/3);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    rotateY(rad) {
        let s = Math.sin(rad);
        let c = Math.cos(rad);
        let a00 = this[0];
        let a01 = this[1];
        let a02 = this[2];
        let a03 = this[3];
        let a20 = this[8];
        let a21 = this[9];
        let a22 = this[10];
        let a23 = this[11];

        // Perform axis-specific matrix multiplication
        this[0] = a00 * c - a20 * s;
        this[1] = a01 * c - a21 * s;
        this[2] = a02 * c - a22 * s;
        this[3] = a03 * c - a23 * s;
        this[8] = a00 * s + a20 * c;
        this[9] = a01 * s + a21 * c;
        this[10] = a02 * s + a22 * c;
        this[11] = a03 * s + a23 * c;
        return this;
    }
    /**
     * 矩阵绕z轴旋转变换
     * @method
     * @public
     * @param {Number} rad 弧度。
     * @example
     * let a=new Mat4([3,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
     * a.rotateZ(Math.PI/3);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    rotateZ(rad) {
        let s = Math.sin(rad);
        let c = Math.cos(rad);
        let a00 = this[0];
        let a01 = this[1];
        let a02 = this[2];
        let a03 = this[3];
        let a10 = this[4];
        let a11 = this[5];
        let a12 = this[6];
        let a13 = this[7];
        // Perform axis-specific matrix multiplication
        this[0] = a00 * c + a10 * s;
        this[1] = a01 * c + a11 * s;
        this[2] = a02 * c + a12 * s;
        this[3] = a03 * c + a13 * s;
        this[4] = a10 * c - a00 * s;
        this[5] = a11 * c - a01 * s;
        this[6] = a12 * c - a02 * s;
        this[7] = a13 * c - a03 * s;
        return this;
    }

    /**
     * 从一个四元数构建4阶矩阵。
     * @method
     * @public
     * @param {Quat} quat 四元数
     * @example
     * let a=new Mat4();
     * let quat=new Quat([0.2,0.4,-0.2,1]);
     * a.fromQuat(quat);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    fromQuat(q) {
        let x = q[0],
            y = q[1],
            z = q[2],
            w = q[3];
        let x2 = x + x;
        let y2 = y + y;
        let z2 = z + z;
        let xx = x * x2;
        let yx = y * x2;
        let yy = y * y2;
        let zx = z * x2;
        let zy = z * y2;
        let zz = z * z2;
        let wx = w * x2;
        let wy = w * y2;
        let wz = w * z2;
        this[0] = 1 - yy - zz;
        this[1] = yx + wz;
        this[2] = zx - wy;
        this[3] = 0;
        this[4] = yx - wz;
        this[5] = 1 - xx - zz;
        this[6] = zy + wx;
        this[7] = 0;
        this[8] = zx + wy;
        this[9] = zy - wx;
        this[10] = 1 - xx - yy;
        this[11] = 0;
        this[12] = 0;
        this[13] = 0;
        this[14] = 0;
        this[15] = 1;
        return this;
    }
    /**
     * 从x轴旋转角度构建4阶矩阵。
     * @method
     * @public
     * @param {Number} rad 弧度
     * @example
     * let a=new Mat4();
     * a.fromXRotation(Math.PI/3);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    fromXRotation(rad) {
        let s = Math.sin(rad);
        let c = Math.cos(rad);

        // Perform axis-specific matrix multiplication
        this[0] = 1;
        this[1] = 0;
        this[2] = 0;
        this[3] = 0;
        this[4] = 0;
        this[5] = c;
        this[6] = s;
        this[7] = 0;
        this[8] = 0;
        this[9] = -s;
        this[10] = c;
        this[11] = 0;
        this[12] = 0;
        this[13] = 0;
        this[14] = 0;
        this[15] = 1;
        return this;
    }
    /**
     * 从y轴旋转角度构建4阶矩阵。
     * @method
     * @public
     * @param {Number} rad 弧度
     * @example
     * let a=new Mat4();
     * a.fromYRotation(Math.PI/3);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    fromYRotation(rad) {
        let s = Math.sin(rad);
        let c = Math.cos(rad);
        // Perform axis-specific matrix multiplication
        this[0] = c;
        this[1] = 0;
        this[2] = -s;
        this[3] = 0;
        this[4] = 0;
        this[5] = 1;
        this[6] = 0;
        this[7] = 0;
        this[8] = s;
        this[9] = 0;
        this[10] = c;
        this[11] = 0;
        this[12] = 0;
        this[13] = 0;
        this[14] = 0;
        this[15] = 1;
        return this;
    }
    /**
     * 从z轴旋转角度构建4阶矩阵。
     * @method
     * @public
     * @param {Number} rad 弧度
     * @example
     * let a=new Mat4();
     * a.fromZRotation(Math.PI/3);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    fromZRotation(rad) {
        const s = Math.sin(rad);
        const c = Math.cos(rad);
        // Perform axis-specific matrix multiplication
        this[0] = c;
        this[1] = s;
        this[2] = 0;
        this[3] = 0;
        this[4] = -s;
        this[5] = c;
        this[6] = 0;
        this[7] = 0;
        this[8] = 0;
        this[9] = 0;
        this[10] = 1;
        this[11] = 0;
        this[12] = 0;
        this[13] = 0;
        this[14] = 0;
        this[15] = 1;
        return this;
    }
    /**
     * 从旋转弧度和轴构建4阶矩阵。
     * @method
     * @public
     * @param {Number} rad 弧度
     * @param {Vec3|Array} axis 轴
     * @example
     * let a=new Mat4();
     * a.fromRotation(Math.PI/3,[0,1,0]);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    fromRotation(rad, axis) {
        const c = Math.cos(rad);
        const s = Math.sin(rad);
        const t = 1 - c;
        let x = axis[0], y = axis[1], z = axis[2];
        let len = Math.sqrt(x * x + y * y + z * z);
        if (len < EPSILON) {
            return null;
        }
        len = 1 / len;
        x *= len;
        y *= len;
        z *= len;
        this[0] = x * x * t + c;
        this[1] = y * x * t + z * s;
        this[2] = z * x * t - y * s;
        this[3] = 0;
        this[4] = x * y * t - z * s;
        this[5] = y * y * t + c;
        this[6] = z * y * t + x * s;
        this[7] = 0;
        this[8] = x * z * t + y * s;
        this[9] = y * z * t - x * s;
        this[10] = z * z * t + c;
        this[11] = 0;
        this[12] = 0;
        this[13] = 0;
        this[14] = 0;
        this[15] = 1;
        return this;
    }
    /**
     * 从平移量构建4阶矩阵。
     * @method
     * @public
     * @param {Vec3|Array} v 平移量
     * @example
     * let a=new Mat4();
     * a.fromTranslation([10,1,10]);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    fromTranslation(v) {
        this[0] = 1;
        this[1] = 0;
        this[2] = 0;
        this[3] = 0;
        this[4] = 0;
        this[5] = 1;
        this[6] = 0;
        this[7] = 0;
        this[8] = 0;
        this[9] = 0;
        this[10] = 1;
        this[11] = 0;
        this[12] = v[0];
        this[13] = v[1];
        this[14] = v[2];
        this[15] = 1;
        return this;
    }
    /**
     * 从缩放量构建4阶矩阵。
     * @method
     * @public
     * @param {Vec3|Array} v 缩放
     * @example
     * let a=new Mat4();
     * a.fromScaling([10,1,10]);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    fromScaling(v) {
        this[0] = v[0];
        this[1] = 0;
        this[2] = 0;
        this[3] = 0;
        this[4] = 0;
        this[5] = v[1];
        this[6] = 0;
        this[7] = 0;
        this[8] = 0;
        this[9] = 0;
        this[10] = v[2];
        this[11] = 0;
        this[12] = 0;
        this[13] = 0;
        this[14] = 0;
        this[15] = 1;
        return this;
    }
    /**
     * 从旋转和平移量构建4阶矩阵。
     * @method
     * @public
     * @param {Quat} q 旋转
     * @param {Vec3|Array} v 平移
     * @example
     * let a=new Mat4();
     * let q=new Quat([0.3,0,0,1]);
     * a.fromRotationTranslation(q,[10,1,10]);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    fromRotationTranslation(q, v) {
        // Quaternion math
        let x = q[0],
            y = q[1],
            z = q[2],
            w = q[3];
        let x2 = x + x;
        let y2 = y + y;
        let z2 = z + z;

        let xx = x * x2;
        let xy = x * y2;
        let xz = x * z2;
        let yy = y * y2;
        let yz = y * z2;
        let zz = z * z2;
        let wx = w * x2;
        let wy = w * y2;
        let wz = w * z2;

        this[0] = 1 - (yy + zz);
        this[1] = xy + wz;
        this[2] = xz - wy;
        this[3] = 0;
        this[4] = xy - wz;
        this[5] = 1 - (xx + zz);
        this[6] = yz + wx;
        this[7] = 0;
        this[8] = xz + wy;
        this[9] = yz - wx;
        this[10] = 1 - (xx + yy);
        this[11] = 0;
        this[12] = v[0];
        this[13] = v[1];
        this[14] = v[2];
        this[15] = 1;
        return this;
    }
    /**
     * 获取平移分量
     * @method
     * @public
     * @returns {Vec3} 平移分量。
     */
    getTranslation() {
        let out = new Vec3();
        out[0] = this[12];
        out[1] = this[13];
        out[2] = this[14];
        return out;
    }
    /**
     * 获取缩放分量
     * @method
     * @public
     * @returns {Vec3} 缩放分量。
     */
    getScaling() {
        let out = new Vec3();
        let m11 = this[0];
        let m12 = this[1];
        let m13 = this[2];
        let m21 = this[4];
        let m22 = this[5];
        let m23 = this[6];
        let m31 = this[8];
        let m32 = this[9];
        let m33 = this[10];
        out[0] = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13);
        out[1] = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23);
        out[2] = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33);
        return out;
    }
    /**
     * 获取旋转分量
     * @method
     * @public
     * @returns {Quat} 旋转分量。
     */
    getRotation() {
        let out = new Quat();
        let scaling = this.getScaling();

        let is1 = 1 / scaling[0];
        let is2 = 1 / scaling[1];
        let is3 = 1 / scaling[2];

        let sm11 = this[0] * is1;
        let sm12 = this[1] * is2;
        let sm13 = this[2] * is3;
        let sm21 = this[4] * is1;
        let sm22 = this[5] * is2;
        let sm23 = this[6] * is3;
        let sm31 = this[8] * is1;
        let sm32 = this[9] * is2;
        let sm33 = this[10] * is3;

        let trace = sm11 + sm22 + sm33;
        let S = 0;
        if (trace > 0) {
            S = Math.sqrt(trace + 1.0) * 2;
            out[3] = 0.25 * S;
            out[0] = (sm23 - sm32) / S;
            out[1] = (sm31 - sm13) / S;
            out[2] = (sm12 - sm21) / S;
        } else if (sm11 > sm22 && sm11 > sm33) {
            S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2;
            out[3] = (sm23 - sm32) / S;
            out[0] = 0.25 * S;
            out[1] = (sm12 + sm21) / S;
            out[2] = (sm31 + sm13) / S;
        } else if (sm22 > sm33) {
            S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2;
            out[3] = (sm31 - sm13) / S;
            out[0] = (sm12 + sm21) / S;
            out[1] = 0.25 * S;
            out[2] = (sm23 + sm32) / S;
        } else {
            S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2;
            out[3] = (sm12 - sm21) / S;
            out[0] = (sm31 + sm13) / S;
            out[1] = (sm23 + sm32) / S;
            out[2] = 0.25 * S;
        }
        return out;
    }
    /**
     * 从旋转和平移量构建4阶矩阵。
     * @method
     * @public
     * @param {Vec3} position 平移
     * @param {Quat} quaternion 旋转
     * @param {Vec3|Array} scale 缩放
     * @example
     * let a=new Mat4();
     * let q=new Quat([0.3,0,0,1]);
     * a.fromRotationTranslation([10,0,0],q,[10,1,10]);
     * @returns {Mat4} 返回一个新的矩阵。
     */
    compose(position, quaternion, scale) {
        const x = quaternion[0], y = quaternion[1], z = quaternion[2], w = quaternion[3];
        const x2 = x + x, y2 = y + y, z2 = z + z;
        const xx = x * x2, xy = x * y2, xz = x * z2;
        const yy = y * y2, yz = y * z2, zz = z * z2;
        const wx = w * x2, wy = w * y2, wz = w * z2;

        const sx = scale[0], sy = scale[1], sz = scale[2];

        this[0] = (1 - (yy + zz)) * sx;
        this[1] = (xy + wz) * sx;
        this[2] = (xz - wy) * sx;
        this[3] = 0;

        this[4] = (xy - wz) * sy;
        this[5] = (1 - (xx + zz)) * sy;
        this[6] = (yz + wx) * sy;
        this[7] = 0;

        this[8] = (xz + wy) * sz;
        this[9] = (yz - wx) * sz;
        this[10] = (1 - (xx + yy)) * sz;
        this[11] = 0;

        this[12] = position[0];
        this[13] = position[1];
        this[14] = position[2];
        this[15] = 1;

        return this;
    }
    /**
     * 获取所有分量
     * @method
     * @public
     * @returns {object} 返回{trans, scale, rotation}
     */
    decompose() {
        let trans = new Vec3();
        let scale = new Vec3();
        let rotation = new Quat();
        trans[0] = this[12];
        trans[1] = this[13];
        trans[2] = this[14];

        let m11 = this[0];
        let m12 = this[1];
        let m13 = this[2];
        let m21 = this[4];
        let m22 = this[5];
        let m23 = this[6];
        let m31 = this[8];
        let m32 = this[9];
        let m33 = this[10];

        scale[0] = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13);
        scale[1] = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23);
        scale[2] = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33);

        let is1 = 1 / scale[0];
        let is2 = 1 / scale[1];
        let is3 = 1 / scale[2];

        let sm11 = m11 * is1;
        let sm12 = m12 * is2;
        let sm13 = m13 * is3;
        let sm21 = m21 * is1;
        let sm22 = m22 * is2;
        let sm23 = m23 * is3;
        let sm31 = m31 * is1;
        let sm32 = m32 * is2;
        let sm33 = m33 * is3;

        let trace = sm11 + sm22 + sm33;
        let S = 0;

        if (trace > 0) {
            S = Math.sqrt(trace + 1.0) * 2;
            rotation[3] = 0.25 * S;
            rotation[0] = (sm23 - sm32) / S;
            rotation[1] = (sm31 - sm13) / S;
            rotation[2] = (sm12 - sm21) / S;
        } else if (sm11 > sm22 && sm11 > sm33) {
            S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2;
            rotation[3] = (sm23 - sm32) / S;
            rotation[0] = 0.25 * S;
            rotation[1] = (sm12 + sm21) / S;
            rotation[2] = (sm31 + sm13) / S;
        } else if (sm22 > sm33) {
            S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2;
            rotation[3] = (sm31 - sm13) / S;
            rotation[0] = (sm12 + sm21) / S;
            rotation[1] = 0.25 * S;
            rotation[2] = (sm23 + sm32) / S;
        } else {
            S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2;
            rotation[3] = (sm12 - sm21) / S;
            rotation[0] = (sm31 + sm13) / S;
            rotation[1] = (sm23 + sm32) / S;
            rotation[2] = 0.25 * S;
        }
        return { trans, scale, rotation };
    }
    /**
     * 转向不影响position
     * @param {*} eye 
     * @param {*} target 
     * @param {*} up 
     * @returns 
     */
    lookAt1( eye, target,up = [0, 1, 0] ) {
		let z=new Vec3(eye);
		z.sub(target);
		if ( z.length() === 0 ) {
			z.z = 1;
		}
		z.normalize();
        let x=new Vec3(up);
		x.cross( z );
		if ( x.length() === 0 ) {
			if ( Math.abs( up.z ) === 1 ) {
				z.x += 0.0001;
			} else {
				z.z += 0.0001;
			}

			z.normalize();
            x=new Vec3(up);
			x.cross(z);

		}
		x.normalize();
        let y=new Vec3(z);
		y.cross( x );

		this[ 0 ] = x.x; this[ 4 ] = y.x; this[ 8 ] = z.x;
		this[ 1 ] = x.y; this[ 5 ] = y.y; this[ 9 ] = z.y;
		this[ 2 ] = x.z; this[ 6 ] = y.z; this[ 10 ] = z.z;
		return this;
	}
    /**
     * 根据给定的眼点位置、焦点和上方向轴生成视图矩阵.
     * 如果你想要一个a对象看到b对象的矩阵，你应该使用targetTo。
     * @method
     * @public
     * @param {Vec3} eye 视点
     * @param {Vec3} center 目标点
     * @param {Vec3} up 上方向
     * @returns {Nat4} 投影矩阵
     */
    lookAt(eye, center, up = [0, 1, 0]) {
        let x0, x1, x2, y0, y1, y2, z0, z1, z2, len;
        let eyex = eye[0];
        let eyey = eye[1];
        let eyez = eye[2];
        let upx = up[0];
        let upy = up[1];
        let upz = up[2];
        let centerx = center[0];
        let centery = center[1];
        let centerz = center[2];

        if (
            Math.abs(eyex - centerx) < EPSILON &&
            Math.abs(eyey - centery) < EPSILON &&
            Math.abs(eyez - centerz) < EPSILON
        ) {
            return identity(out);
        }

        z0 = eyex - centerx;
        z1 = eyey - centery;
        z2 = eyez - centerz;

        len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
        z0 *= len;
        z1 *= len;
        z2 *= len;

        x0 = upy * z2 - upz * z1;
        x1 = upz * z0 - upx * z2;
        x2 = upx * z1 - upy * z0;
        len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
        if (!len) {
            x0 = 0;
            x1 = 0;
            x2 = 0;
        } else {
            len = 1 / len;
            x0 *= len;
            x1 *= len;
            x2 *= len;
        }

        y0 = z1 * x2 - z2 * x1;
        y1 = z2 * x0 - z0 * x2;
        y2 = z0 * x1 - z1 * x0;

        len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
        if (!len) {
            y0 = 0;
            y1 = 0;
            y2 = 0;
        } else {
            len = 1 / len;
            y0 *= len;
            y1 *= len;
            y2 *= len;
        }

        this[0] = x0;
        this[1] = y0;
        this[2] = z0;
        this[3] = 0;
        this[4] = x1;
        this[5] = y1;
        this[6] = z1;
        this[7] = 0;
        this[8] = x2;
        this[9] = y2;
        this[10] = z2;
        this[11] = 0;
        this[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
        this[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
        this[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
        this[15] = 1;

        return this;
    }
    /**
     * 构建a对象看到b对象的矩阵
     * @method
     * @public
     * @param {Vec3} eye 视点
     * @param {Vec3} center 目标点
     * @param {Vec3} up 上方向
     * @returns {Nat4} 投影矩阵
     */
    targetTo(eye, target, up = [0, 1, 0]) {
        let eyex = eye[0],
            eyey = eye[1],
            eyez = eye[2],
            upx = up[0],
            upy = up[1],
            upz = up[2];

        let z0 = eyex - target[0],
            z1 = eyey - target[1],
            z2 = eyez - target[2];

        let len = z0 * z0 + z1 * z1 + z2 * z2;
        if (len > 0) {
            len = 1 / Math.sqrt(len);
            z0 *= len;
            z1 *= len;
            z2 *= len;
        }

        let x0 = upy * z2 - upz * z1,
            x1 = upz * z0 - upx * z2,
            x2 = upx * z1 - upy * z0;

        len = x0 * x0 + x1 * x1 + x2 * x2;
        if (len > 0) {
            len = 1 / Math.sqrt(len);
            x0 *= len;
            x1 *= len;
            x2 *= len;
        }

        this[0] = x0;
        this[1] = x1;
        this[2] = x2;
        this[3] = 0;
        this[4] = z1 * x2 - z2 * x1;
        this[5] = z2 * x0 - z0 * x2;
        this[6] = z0 * x1 - z1 * x0;
        this[7] = 0;
        this[8] = z0;
        this[9] = z1;
        this[10] = z2;
        this[11] = 0;
        this[12] = eyex;
        this[13] = eyey;
        this[14] = eyez;
        this[15] = 1;
        return this;
    }
    /**
     * 生成适用于给定边界的WebGPU的透视投影矩阵。
     * 近/远剪切平面对应于[0,1]的归一化设备坐标Z范围，这与WebGPU/Vulkan/DDirectX/Metal的剪辑量相匹配。
     * 为far传递null/undefined/no值将生成无限投影矩阵。
     * @method
     * @public
     * @param {Number} fovy 视角，单位弧度。
     * @param {Number} aspect 宽高比
     * @param {Number} near 近裁面
     * @param {Number} far 远裁面
     * @returns {Mat4} 投影矩阵
     */
    perspective(fovy, aspect, near, far) {
        const f = 1.0 / Math.tan(fovy / 2);
        this[0] = f / aspect;
        this[1] = 0;
        this[2] = 0;
        this[3] = 0;
        this[4] = 0;
        this[5] = f;
        this[6] = 0;
        this[7] = 0;
        this[8] = 0;
        this[9] = 0;
        this[11] = -1;
        this[12] = 0;
        this[13] = 0;
        this[15] = 0;
        if (far != null && far !== Infinity) {
            const nf = 1 / (near - far);
            this[10] = far * nf;
            this[14] = far * near * nf;
        } else {
            this[10] = -1;
            this[14] = -near;
        }
        return this;
    }
    /**
     * 生成具有给定边界的正交投影矩阵。
     * 近/远剪切平面对应于[0,1]的归一化设备坐标Z范围,这与WebGPU/Vulkan/DDirectX/Metal的剪辑量相匹配。
     * @method
     * @public
     * @param {Number} left 视景体左边界
     * @param {Number} right 视景体右边界
     * @param {Number} bottom 视景体下边界
     * @param {Number} top 视景体上边界
     * @param {Number} near 视景体近裁面
     * @param {Number} far 视景体远裁面
     * @returns {Mat4} 正射投影矩阵
     */
    ortho(left, right, bottom, top, near, far) {
        const lr = 1 / (left - right);
        const bt = 1 / (bottom - top);
        const nf = 1 / (near - far);
        this[0] = -2 * lr;
        this[1] = 0;
        this[2] = 0;
        this[3] = 0;
        this[4] = 0;
        this[5] = -2 * bt;
        this[6] = 0;
        this[7] = 0;
        this[8] = 0;
        this[9] = 0;
        this[10] = nf;
        this[11] = 0;
        this[12] = (left + right) * lr;
        this[13] = (top + bottom) * bt;
        this[14] = near * nf;
        this[15] = 1;
        return this;
    }
    /**
     * 生成具有给定边界的截头体矩阵
     * @method
     * @public
     * @param {Number} left 视景体左边界
     * @param {Number} right 视景体右边界
     * @param {Number} bottom 视景体下边界
     * @param {Number} top 视景体上边界
     * @param {Number} near 视景体近裁面
     * @param {Number} far 视景体远裁面
     * @returns {Mat4} out
     */
    frustum(left, right, bottom, top, near, far) {
        let rl = 1 / (right - left);
        let tb = 1 / (top - bottom);
        let nf = 1 / (near - far);
        this[0] = near * 2 * rl;
        this[1] = 0;
        this[2] = 0;
        this[3] = 0;
        this[4] = 0;
        this[5] = near * 2 * tb;
        this[6] = 0;
        this[7] = 0;
        this[8] = (right + left) * rl;
        this[9] = (top + bottom) * tb;
        this[10] = (far + near) * nf;
        this[11] = -1;
        this[12] = 0;
        this[13] = 0;
        this[14] = far * near * 2 * nf;
        this[15] = 0;
        return this;
    }
    /**
     * 转为字符串
     * @method
     * @public
     * @returns {String} 矩阵的字符串。
     */
    toString() {
        return `Mat4(${this.join(',')})`
    }
}
export { Mat4 }